﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq.Expressions;

namespace MicroDal
{
    internal class MapCache
    {
        private Dictionary<long, LambdaExpression> cache = new Dictionary<long, LambdaExpression>();
        private object _lock = new object();

        public Func<DbDataReader, T> Get<T>()
        {
            var key = typeof(T).GetHashCode();
            if (!cache.ContainsKey(key))
            {
                Tracer.WriteTrace("Cache didn't contain mapper of type: {0}", typeof(T).Name);
                lock (_lock)
                {
                    if (!cache.ContainsKey(key))
                    {
                        Bind(key, MapGenerator.DbDataReaderMapper<T>());
                    }
                }
            }
            var cacheitem = cache[key];
            var lambda = Expression.Lambda<Func<DbDataReader, T>>(cacheitem.Body, cacheitem.Parameters);
            var function = lambda.Compile();
            return function;
        }

        public void Bind(long key, LambdaExpression func)
        {
            if (func == null)
                throw new ArgumentNullException();

            Tracer.WriteTrace("Setting cache key: {0}", key);

            lock (_lock)
            {
                Tracer.WriteTrace("Expression:\n{0}", func.Body);
                if (cache.ContainsKey(key))
                    cache[key] = func;
                else
                    cache.Add(key, func);
            }
        }

    }
}
